﻿using Microsoft.EntityFrameworkCore;
using TuLing.Dto;
using TuLing.Entities;
using TuLing.IServices;

namespace TuLing.Services
{
    public class RBACRoleService : BaseService, IRBACRoleService
    {
        public RBACRoleService(DefaultDbContext context) : base(context) { }
        
        public async Task<List<RoleDto>> GetListAsync(string keyword="")
        {
            if (!string.IsNullOrEmpty(keyword))
            {
                var listPart = await _context.Roles.AsNoTracking().Where(m => m.Name.Contains(keyword)).ToListAsync();
                return listPart.Select(r => new RoleDto() 
                { 
                    Id = r.Id, 
                    Name = r.Name, 
                    Remark = r.Remark 
                }).ToList();
            }
            var listAll = await _context.Roles.ToListAsync();
            return listAll.Select(r => new RoleDto() 
            { 
                Id = r.Id, 
                Name = r.Name, 
                Remark = r.Remark 
            }).ToList();
        }

        public async Task<List<RoleDto>> GetRolesByUser(long userId)
        {
            var roles = await _context.Users.Where(u => u.Id == userId)
                                            .SelectMany(r => r.UserRoles)
                                            .Select(rp => rp.Role).ToListAsync();
            
            return roles.Select(r => new RoleDto(){ 
                Id = r.Id, 
                Name = r.Name, 
                Remark = r.Remark 
            }).ToList();
        }

        public async Task Delete(long id)
        {
            var role = await _context.Roles.FirstOrDefaultAsync(s => s.Id == id);
            if (role != null)
            {
                _context.Roles.Remove(role!);
                await _context.SaveChangesAsync();
            }
            throw new Exception("Not found.");
        }

        public async Task Save(RoleDto input)
        {
            if (input.Id == 0)
            {
                var hasData = await _context.Roles.FirstOrDefaultAsync(m => m.Name == input.Name);
                if (hasData != null)
                {
                    throw new Exception("名称已存在。");
                }

                var role = new Role()
                {
                    Name = input.Name,
                    Remark = input.Remark,
                };
                _context.Roles.Add(role);
                await _context.SaveChangesAsync();

                input.Id = role.Id;
            }
            else
            {
                var hasData = _context.Roles.FirstOrDefault(m => m.Id != input.Id && m.Name == input.Name);
                if (hasData != null)
                    throw new Exception("已存在此角色名称");

                var role = await _context.Roles.FirstOrDefaultAsync(m => m.Id == input.Id);
                if (role == null)
                    throw new Exception("角色不存在");

                role.Name = input.Name;
                role.Remark = input.Remark;
                _context.Roles.Update(role);
                await _context.SaveChangesAsync();
            }
        }
    }
}
